// #include "../src/EventHash.h"
#include "../src/EventObject.h"

#include <stdio.h>

#define test_len       5112
#define table_size     5112
#define slot_size      4000
#define print_result   0
#define seed_range_min 1
#define seed_range_max 215410

euint32
hash(epointer key, euint32 seed)
{
	euint32 sum  = 0;
	euint64 _key = (euint64)key;

	do {
		sum += seed * _key;
		_key = (_key - _key % 17) / 17;
	} while (_key > 17);

	return sum % table_size;
}

euint32
get_min_slot(euint32 *test_number, euint32 *slot, euint32 seed)
{
	euint32 tmp, kind = 0;
	bool	flag;

	for (euint64 i = 0; i < test_len; ++i)
		test_number[i] = hash((epointer)i + 5000, seed);

	while (1) {
		flag = false;
		for (int i = 0; i < test_len - 1; ++i) {
			if (test_number[i] > test_number[i + 1]) {
				tmp		   = test_number[i];
				test_number[i]	   = test_number[i + 1];
				test_number[i + 1] = tmp;
				flag		   = true;
			}
		}
		if (!flag)
			break;
	}

	/* 分析哈希槽 */
	euint32 now, slot_num = 0;
	now = table_size;
	for (int i = 0; i < test_len; ++i) {
		if (test_number[i] != now) {
			kind += 1;
			now   = test_number[i];
			if (slot_num < slot_size)
				slot[slot_num] += 1;
			slot_num = 1;
		} else {
			slot_num += 1;
		}
	}
	slot[0] = table_size - kind;
	return (table_size - kind);
}

int
main(void)
{
	euint32 test_number[test_len] = { 0 }, tmp, kind = 0,
		slot[slot_size] = { 0 };
	bool flag;

	printf("生成哈希数组 ......\n");
	for (euint64 i = 0; i < test_len; ++i)
		test_number[i] = hash((epointer)i + 230, 17);

	printf("对生成结果排序中 ......\n");
	while (1) {
		flag = false;
		for (int i = 0; i < test_len - 1; ++i) {
			if (test_number[i] > test_number[i + 1]) {
				tmp		   = test_number[i];
				test_number[i]	   = test_number[i + 1];
				test_number[i + 1] = tmp;
				flag		   = true;
			}
		}
		if (!flag)
			break;
	}

#if print_result == 1
	printf("打印结果 ......\n");
	for (int i = 0; i < test_len; ++i)
		printf("%d\t", test_number[i]);
	printf("\n");
#endif

	printf("分析结果 ......\n");
	/* 分析哈希槽 */
	euint32 now, slot_num = 0;
	now = table_size;
	for (int i = 0; i < test_len; ++i) {
		if (test_number[i] != now) {
			kind += 1;
			now   = test_number[i];
			if (slot_num < slot_size)
				slot[slot_num] += 1;
			slot_num = 1;
		} else {
			slot_num += 1;
		}
	}
	slot[0] = table_size - kind;
	printf("表大小:   \t%d\n", table_size);
	printf("插入元素个数:\t%d\n", test_len);
	printf("理想无元素哈希槽个数: %d\n", table_size - test_len);
	printf("没有元素的哈希槽个数: %d\n", slot[0]);
	for (int i = 1; i < slot_size; ++i)
		if (slot[i] != 0)
			printf("有 %d 个元素的哈希槽: %d\n", i, slot[i]);

	printf("寻找最少空闲槽的种子 ......\n");
	euint32 min_slot = table_size, now_slot;
	for (euint32 i = seed_range_min; i < seed_range_max; ++i) {
		for (int i = 0; i < slot_size; ++i)
			slot[i] = 0;
		now_slot = get_min_slot(test_number, slot, i);
		printf("\r检测种子 '%u', 比率: %.02f%% ......", i,
		       ((double)now_slot / (double)table_size) * 100.0);
		fflush(stdout);
		if (now_slot < min_slot) {
			printf("寻找到种子: %d\n", i);
			for (int i = 0; i < slot_size; ++i)
				if (slot[i] != 0)
					printf("有 %d 个元素的哈希槽: %d\n", i,
					       slot[i]);
			min_slot = now_slot;
		}
	}
	printf("\n结束\n");

	return 0;
}